/*
 * =====================================================================================
 *
 *       Filename:  cl_timestamp.hxx
 *
 *    Description:  
 *
 *        Version:  1.0
 *        Created:  02/27/2011 02:32:15 PM
 *       Revision:  none
 *       Compiler:  gcc
 *
 *         Author:  Ken Chen (Ken), chen_kenz@emc.com
 *        Company:  EMC
 *
 * =====================================================================================
 */

#ifndef _CL_TIME_STAMP_HXX_
#define _CL_TIME_STAMP_HXX_

#ifndef __GXX_EXPERIMENTAL_CXX0X__
#define __GXX_EXPERIMENTAL_CXX0X__
#endif

#include <cstdlib>
#include <cstdint>
#include <sys/time.h>
#include <string>
#include <iostream>

namespace neo
{

/////////
class CLTimestamp
{
public:
  explicit CLTimestamp(int secs = 0, int msecs = 0);
  bool operator>(const CLTimestamp& other) const;
  bool operator<(const CLTimestamp& other) const;
  bool operator==(const CLTimestamp& other) const;
  CLTimestamp& operator+=(int msecs);
  const CLTimestamp operator+(int msecs) const;
  static const CLTimestamp nowTime(void);
  static const CLTimestamp nullTime(void);
  void getTime(int& secs, int& msecs) const;
  const std::string toString(void) const;
  const std::string toFormatString(void) const;

public:
  const static int MICROSECOND_PER_SECOND = 1000000;

private:
  struct timeval m_timeStamp;
};

inline const CLTimestamp operator+(int msecs, const CLTimestamp& rhs)
{
  CLTimestamp ts(rhs);
  return ts+msecs;
}

inline std::ostream& operator<<(std::ostream& os, const CLTimestamp& ts)
{
  return os << ts.toString();
}

// return 0 if lhs equals rhs, 
// return 1, if lhs is later(big) than rhs,
// return -1, if lhs is earlier(less) than rhs.
// deltaSecs and deltaMsecs are the delta
inline int clTimestampDiff(const CLTimestamp& lhs, 
                            const CLTimestamp& rhs, 
                            int& deltaSecs, 
                            int& deltaMsecs)
{
	int lhsSecs = 0;
  int lhsMsecs = 0;
	lhs.getTime(lhsSecs, lhsMsecs);

 	int rhsSecs = 0;
  int rhsMsecs = 0;
	rhs.getTime(rhsSecs, rhsMsecs);
 
  int64_t lhsTotalMsecs = (lhsSecs * CLTimestamp::MICROSECOND_PER_SECOND) + lhsMsecs;
  int64_t rhsTotalMsecs = (rhsSecs * CLTimestamp::MICROSECOND_PER_SECOND) + rhsMsecs;
	deltaSecs = (abs(lhsTotalMsecs - rhsTotalMsecs))/CLTimestamp::MICROSECOND_PER_SECOND;
	deltaMsecs = (abs(lhsTotalMsecs - rhsTotalMsecs))%CLTimestamp::MICROSECOND_PER_SECOND;
	if(lhsTotalMsecs > rhsTotalMsecs)
	{
		return 1;
	}
	else if(lhsTotalMsecs == rhsTotalMsecs)
	{
		return 0;
	}
	else
	{
		return -1;
	}
}

} // neo

#endif //_CL_TIME_STAMP_H_

